﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YJKRevitKernel.ElementSearchUtility.LinkDocumentSuite;
using YJKRevitKernel.FormUtility.ModelessFormControlSuite;
using YJKGeometryFuncs;
using YJKGeometryFuncs.CurveUtility;
using YJKRevitView;
using YJKInspectModelFunc.ControlLayer;
using YJKInspectModelFunc.ModelLayer;
using YJKInspectModelFunc.Properties;

namespace YJKInspectModelFunc
{
	public static class Utility
	{
		private static bool CalDoorWidthPointInWallCurve(BaseDoorPacker inputDoorPacker, ref List<XYZ> tempPoint_UnProject)
		{
			tempPoint_UnProject = Utility.GetFamilyInstanceWidthPointAtlWallLocation(inputDoorPacker.ThisDoor, inputDoorPacker.UseTransform, inputDoorPacker.ThisLimitGeometryPacker);
			return tempPoint_UnProject != null && tempPoint_UnProject.Count != 0;
		}

		private static bool CalTwoDoorMinDistance(List<XYZ> oneDoorWidthPoints, List<XYZ> twoDoorWidthPoints, ref double minLength)
		{
			foreach (XYZ xyz in oneDoorWidthPoints)
			{
				foreach (XYZ xyz2 in twoDoorWidthPoints)
				{
					double num = xyz.DistanceTo(xyz2);
					if (Geometry.LessThan(num, minLength))
					{
						minLength = num;
					}
				}
			}
			return minLength != double.MaxValue;
		}

		public static bool CalTowDoorMinDistance(BaseDoorPacker oneInputDoorPacker, BaseDoorPacker twoInputDoorPacker, ref double minLength)
		{
			List<XYZ> oneDoorWidthPoints = new List<XYZ>();
			List<XYZ> twoDoorWidthPoints = new List<XYZ>();
			if (oneInputDoorPacker.ThisElement.Id.IntegerValue == 1246714 && twoInputDoorPacker.ThisElement.Id.IntegerValue == 1246717)
			{
				twoDoorWidthPoints = new List<XYZ>();
			}
			return Utility.CalDoorWidthPointInWallCurve(oneInputDoorPacker, ref oneDoorWidthPoints) && Utility.CalDoorWidthPointInWallCurve(twoInputDoorPacker, ref twoDoorWidthPoints) && Utility.CalTwoDoorMinDistance(oneDoorWidthPoints, twoDoorWidthPoints, ref minLength);
		}

		public static List<X> GetGenericElementsByView<X>(Autodesk.Revit.DB.Document m_doc, ElementId useViewId, BuiltInCategory useBuiltIncategory, bool bIsLink = false) where X : BaseLinkDocumentResultBean
		{
			List<X> list = new List<X>();
			List<double> list2 = new List<double>();
			foreach (Element element in new FilteredElementCollector(m_doc).OfClass(typeof(Level)))
			{
				if (element != null && element is Level)
				{
					list2.Add((element as Level).Elevation);
				}
			}
			ViewPlan viewPlan = m_doc.GetElement(useViewId) as ViewPlan;
			BoundingBoxIntersectsFilter input = null;
			list2 = (from k in list2
			orderby k
			select k).ToList<double>();
			LinkDocumentUtility.GetViewBox(viewPlan, list2, ref input);
			FilteredElementCollectorLinkDocument filteredElementCollectorLinkDocument = new FilteredElementCollectorLinkDocument(m_doc);
			filteredElementCollectorLinkDocument.OfCategory(useBuiltIncategory);
			filteredElementCollectorLinkDocument.AddViewLimit(input);
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in filteredElementCollectorLinkDocument.ToBeans())
			{
				X x = (X)((object)baseLinkDocumentResultBean);
				if (x != null)
				{
					list.Add(x);
				}
			}
			return list;
		}

		public static List<X> GetGenericAreasByView<X>(Autodesk.Revit.DB.Document m_doc, ElementId useViewId, BuiltInCategory useBuiltIncategory, bool bIsLink = false) where X : Element
		{
			List<X> list = new List<X>();
			new List<double>();
			foreach (Element element in new FilteredElementCollector(m_doc, useViewId).OfCategory(useBuiltIncategory))
			{
				X x = (X)((object)element);
				if (x != null)
				{
					list.Add(x);
				}
			}
			return list;
		}

		public static List<Area> GetAllAreaByView(Autodesk.Revit.DB.Document m_doc, ElementId viewId, bool bisLink = false)
		{
			return Utility.GetGenericAreasByView<Area>(m_doc, viewId, BuiltInCategory.OST_Areas, false);
		}

		public static List<Area> GetAllAreaByView(Autodesk.Revit.DB.View useView)
		{
			return Utility.GetAllAreaByView(useView.Document, useView.Id, false);
		}

		public static List<BaseLinkDocumentResultBean> GetAllWallByView(Autodesk.Revit.DB.Document m_doc, ElementId viewId)
		{
			return Utility.GetGenericElementsByView<BaseLinkDocumentResultBean>(m_doc, viewId, BuiltInCategory.OST_Walls, false);
		}

		public static List<BaseLinkDocumentResultBean> GetAllWallByView(Autodesk.Revit.DB.View useView)
		{
			return Utility.GetAllWallByView(useView.Document, useView.Id);
		}

		public static List<BaseLinkDocumentResultBean> GetAllWinDoorByView(Autodesk.Revit.DB.Document m_doc, ElementId viewId)
		{
			List<BaseLinkDocumentResultBean> list = new List<BaseLinkDocumentResultBean>();
			list.AddRange(Utility.GetGenericElementsByView<BaseLinkDocumentResultBean>(m_doc, viewId, BuiltInCategory.OST_Doors, false));
			list.AddRange(Utility.GetGenericElementsByView<BaseLinkDocumentResultBean>(m_doc, viewId, BuiltInCategory.OST_Windows, false));
			return list;
		}

		public static List<BaseLinkDocumentResultBean> GetAllWinDoorByView(Autodesk.Revit.DB.View useView)
		{
			return Utility.GetAllWinDoorByView(useView.Document, useView.Id);
		}

		public static bool IfEnvironmentCanUse(ExternalCommandData commandData)
		{
			CmdViewType types = CmdViewType.FloorPlan;
			if (SwitchView.SetUsableView(types, commandData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return false;
			}
			if (Convert.ToInt32(commandData.Application.Application.VersionNumber) < 2016)
			{
				YJKMessageBox.Show("此功能只在Revit2016及其以上版本可用。");
				return false;
			}
			return true;
		}

		public static string GetFireAreaString(Area inputArea)
		{
			string text = string.Empty;
			if (inputArea == null)
			{
				return text;
			}
			string result;
			try
			{
				IList<Parameter> parameters = inputArea.GetParameters(Resources.Str_FireAreaNameParameter);
				if (parameters != null && parameters.Count != 0)
				{
					text = parameters.ElementAt(0).AsString();
				}
				IList<Parameter> parameters2 = inputArea.GetParameters(Resources.Str_FireAreaNumberParameter);
				if (parameters2 != null && parameters2.Count != 0)
				{
					text += parameters2.ElementAt(0).AsString();
				}
				result = text;
			}
			catch (Exception)
			{
				result = inputArea.Name;
			}
			return result;
		}

		public static bool TryGetEnityValue<T>(Element inputElemnt, string strGuid, string strFieldName, out T findeValue)
		{
			findeValue = default(T);
			bool result;
			try
			{
				Schema schema = Schema.Lookup(new Guid(strGuid));
				if (schema == null)
				{
					result = false;
				}
				else
				{
					Entity entity = inputElemnt.GetEntity(schema);
					if (entity == null || entity.Schema == null)
					{
						result = false;
					}
					else
					{
						Field field = schema.GetField(strFieldName);
						if (field == null)
						{
							result = false;
						}
						else
						{
                            findeValue = entity.Get<T>(field, (DisplayUnitType)6);
							result = true;
						}
					}
				}
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public static bool IfAreaIsFireAreWithOtherData(Area input, List<Level> inputLevel)
		{
			bool flag = Utility.IfAreaIsFireArea(input, inputLevel);
			bool flag2 = false;
			double num = 0.0;
			return flag && Utility.TryReadAreaOtherData(input, out flag2, out num);
		}

		public static bool IfAreaIsFireArea(Area input, List<Level> inputLevel)
		{
			Document document = input.Document;
			List<int> list = new List<int>();
			Guid guid = new Guid(Resources.Str_GUIDforFireArea);
			Schema schema = Schema.Lookup(guid);
			if (input == null || inputLevel == null || input.Level == null)
			{
				return false;
			}
			if (input.GetBoundarySegments(new SpatialElementBoundaryOptions()) == null || input.GetBoundarySegments(new SpatialElementBoundaryOptions()).Count == 0)
			{
				return false;
			}
			foreach (Level level in inputLevel)
			{
				list.Add(level.Id.IntegerValue);
			}
			if (schema == null || !schema.SchemaName.Equals(Resources.Str_SchemaNameofFireArea))
			{
				return false;
			}
			Entity entity = input.GetEntity(Schema.Lookup(guid));
			return entity != null && entity.Schema != null && list.Contains(input.Level.Id.IntegerValue);
		}

		public static bool TryReadAreaOtherData(Area inputArea, out bool ifSpary, out double peopleDensity)
		{
			ifSpary = true;
			peopleDensity = 0.0;
			try
			{
				Schema schema = Schema.Lookup(new Guid(Resources.Str_SparyGuid));
				if (schema != null)
				{
					Entity entity = inputArea.GetEntity(schema);
					if (entity != null && entity.Schema != null)
					{
						Field field = schema.GetField("IsWithSpary");
						if (entity.Get<string>(field).ToLower().Contains("n"))
						{
							ifSpary = false;
						}
						Field field2 = schema.GetField("PeopleDensity");
						string text = entity.Get<string>(field2);
						if (string.IsNullOrEmpty(text))
						{
							peopleDensity = 0.0;
							return true;
						}
						return double.TryParse(text, out peopleDensity);
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static List<BaseRoomPacker> FindOtherConctRoomsExpectInput(BaseDoorPacker inputDoor, BaseRoomPacker inputRoom)
		{
			return (from n in inputDoor.LstConctRooms
			where n.ThisElementPackerId != inputRoom.ThisElementPackerId
			select n).ToList<BaseRoomPacker>();
		}

		public static void SendEscToHandle(IWin32Window inputHandle)
		{
			Utility.SendEscToHandle(inputHandle);
		}

		public static void AddRoomToNoneRoomPlace(Autodesk.Revit.DB.Document useDocument, List<Level> useListLevel, List<Phase> useListPhase)
		{
			List<int> list = new List<int>();
			Transaction transaction = new Transaction(useDocument, "addRoom");
			try
			{
				transaction.Start();
				Room room = null;
				foreach (Level level in useListLevel)
				{
					foreach (Phase phase in useListPhase)
					{
						foreach (object obj in useDocument.get_PlanTopology(level, phase).Circuits)
						{
							PlanCircuit planCircuit = (PlanCircuit)obj;
							if (!planCircuit.IsRoomLocated)
							{
								try
								{
									room = useDocument.Create.NewRoom(null, planCircuit);
								}
								catch (Exception)
								{
									continue;
								}
								if (room != null)
								{
									list.Add(room.Id.IntegerValue);
								}
							}
						}
					}
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				if (transaction.HasStarted())
				{
					transaction.RollBack();
				}
			}
			ElementPackerManger.LstAddRoomIds = list;
		}

		public static void AddRoomToNoneRoomPlace(Autodesk.Revit.DB.Document useDocument, List<Level> useListLevel)
		{
			List<Phase> list = new List<Phase>();
			foreach (object obj in useDocument.Phases)
			{
				Phase item = (Phase)obj;
				list.Add(item);
			}
			Utility.AddRoomToNoneRoomPlace(useDocument, useListLevel, list);
		}

		public static void DeleteAddRoom(Autodesk.Revit.DB.Document useDoc, List<int> lstDontDeleteRoomId)
		{
			Transaction transaction = new Transaction(useDoc, "deleteRoom");
			try
			{
				transaction.Start();
				ElementPackerManger.TryDeletedAddedRoom(useDoc, lstDontDeleteRoomId);
				transaction.Commit();
			}
			catch (Exception)
			{
				if (transaction.HasStarted())
				{
					transaction.RollBack();
				}
			}
		}

		public static List<Level> GetAllLevels(Autodesk.Revit.DB.Document inputDoc)
		{
			return FloorSelectManager.GetSortLevels(inputDoc, double.MinValue, double.MaxValue);
		}

		public static string GetAppRootPath()
		{
			string location = Assembly.GetExecutingAssembly().Location;
			int length = location.LastIndexOf("\\");
			string text = location.Substring(0, length);
			length = text.LastIndexOf("\\");
			return text.Substring(0, length);
		}

		public static bool IfDoorIsOutSideDoor(BaseDoorPacker input)
		{
			if (input.LstConctRooms.Count == 1)
			{
				double nowDownZ = input.LstConctRooms[0].NowDownZ;
				XYZ xyz = (input.ThisElement as FamilyInstance).FacingOrientation;
				if (input.UseTransform != null)
				{
					xyz = Geometry.TransformPoint(xyz, input.UseTransform);
				}
				XYZ xyz2 = input.ThisLimitGeometryPacker.CenterPoint;
				xyz2 = new XYZ(xyz2.X, xyz2.Y, nowDownZ);
				Wall wall = (input.ThisElement as FamilyInstance).Host as Wall;
				if (wall != null)
				{
					double num = wall.Width;
					num /= 2.0;
					num += double.Parse(Resources.Str_ValueForOutDoorCheckOffest);
					XYZ xyz3 = xyz2.Add(xyz.Multiply(num));
					XYZ xyz4 = xyz2.Add(-xyz.Multiply(num));
					if (input.LstConctRooms[0].ThisRoom.IsPointInRoom(xyz3) && input.LstConctRooms[0].ThisRoom.IsPointInRoom(xyz4))
					{
						return false;
					}
				}
				return true;
			}
			return false;
		}

		public static List<List<BaseDoorPacker>> GroupDoorsByDistance(List<BaseDoorPacker> inputValue, double useDistance, string filterName = null)
		{
			List<List<BaseDoorPacker>> list = new List<List<BaseDoorPacker>>();
			List<BaseDoorPacker> list2 = new List<BaseDoorPacker>();
			list2.AddRange(inputValue);
			int num = 0;
			list2.RemoveAll((BaseDoorPacker k) => !k.ThisLimitGeometryPacker.IfCanUse);
			if (filterName != null)
			{
				list2.RemoveAll((BaseDoorPacker k) => Regex.IsMatch(k.FamilyName, filterName));
			}
			list2 = list2.OrderBy(Utility.OrderDoorByDistance(inputValue)).ToList<BaseDoorPacker>();
			if (1 == list2.Count)
			{
				list.Add(new List<BaseDoorPacker>());
				list[0].Add(inputValue[0]);
			}
			for (int i = 0; i < list2.Count - 1; i++)
			{
				int num2 = i + 1;
				BaseDoorPacker baseDoorPacker = list2[i];
				BaseDoorPacker baseDoorPacker2 = list2[i + 1];
				double num3 = Utility.GetDoorWidth(baseDoorPacker);
				double num4 = Utility.GetDoorWidth(baseDoorPacker2);
				if (num3 < 0.0 && num4 < 0.0)
				{
					num3 = 0.0;
					num4 = 0.0;
				}
				else if (num3 < 0.0 || num4 < 0.0)
				{
					num3 = Math.Max(num3, num4);
					num4 = Math.Max(num3, num4);
				}
				if (Utility.NoneZDistance(baseDoorPacker.ThisLimitGeometryPacker.CenterPoint, baseDoorPacker2.ThisLimitGeometryPacker.CenterPoint) - 0.5 * num3 - 0.5 * num4 > useDistance)
				{
					list.Add(new List<BaseDoorPacker>());
					for (int j = num; j < num2; j++)
					{
						list[list.Count - 1].Add(list2[j]);
					}
					num = num2;
					num2++;
				}
				if (num2 >= list2.Count - 1 && num != num2)
				{
					list.Add(new List<BaseDoorPacker>());
					for (int l = num; l < Math.Min(num2, list2.Count); l++)
					{
						list[list.Count - 1].Add(list2[l]);
					}
					num = num2;
				}
			}
			return list;
		}

		public static double NoneZDistance(XYZ inputOne, XYZ inputTwo)
		{
			XYZ xyz = new XYZ(inputOne.X, inputOne.Y, 0.0);
			XYZ xyz2 = new XYZ(inputTwo.X, inputTwo.Y, 0.0);
			return xyz.DistanceTo(xyz2);
		}

		public static double GetDoorWidth(BaseDoorPacker inputDoor)
		{
			Parameter parameter = inputDoor.ThisDoor.Symbol.get_Parameter((BuiltInParameter)Enum.Parse(typeof(BuiltInParameter), Resources.Str_ParameterName_Width));
			if (parameter == null)
			{
				return -1.0;
			}
			return parameter.AsDouble();
		}

		private static Func<BaseDoorPacker, double> OrderDoorByDistance(List<BaseDoorPacker> inputValue)
		{
			return (BaseDoorPacker k) => k.ThisLimitGeometryPacker.CenterPoint.DistanceTo(inputValue[0].ThisLimitGeometryPacker.CenterPoint);
		}

		public static bool IfDoorToRoom(BaseDoorPacker inputPacker, Room inputRoom)
		{
			if (!inputPacker.ThisLimitGeometryPacker.IfCanUse)
			{
				return false;
			}
			XYZ realFacingOrientation = Utility.GetRealFacingOrientation(inputPacker);
			double num = (inputPacker.ThisDoor.Host as Wall).Width;
			num /= 2.0;
			XYZ point = (inputRoom.Location as LocationPoint).Point;
			XYZ xyz = inputPacker.ThisLimitGeometryPacker.CenterPoint.Add(realFacingOrientation.Multiply(num));
			XYZ xyz2 = inputPacker.ThisLimitGeometryPacker.CenterPoint.Add(-realFacingOrientation.Multiply(num));
			return Geometry.LessThan(xyz.DistanceTo(point), xyz2.DistanceTo(point));
		}

		public static XYZ GetAMovePointForDoorToRoom(BaseDoorPacker inputPacker, Room inputRoom, double moveDistance = -1.0)
		{
			if (!inputPacker.ThisLimitGeometryPacker.IfCanUse)
			{
				return null;
			}
			XYZ realFacingOrientation = Utility.GetRealFacingOrientation(inputPacker);
			XYZ xyz = inputPacker.ThisLimitGeometryPacker.CenterPoint;
			xyz = new XYZ(xyz.X, xyz.Y, inputRoom.Level.Elevation);
			double num = moveDistance;
			if (num < 0.0)
			{
				num = (inputPacker.ThisDoor.Host as Wall).Width;
			}
			if (Utility.IfDoorToRoom(inputPacker, inputRoom) && inputRoom.IsPointInRoom(xyz.Add(realFacingOrientation.Multiply(num))))
			{
				return xyz.Add(realFacingOrientation.Multiply(num));
			}
			return xyz.Add(-realFacingOrientation.Multiply(num));
		}

		public static XYZ GetRealFacingOrientation(BaseDoorPacker inputPacker)
		{
			XYZ xyz = inputPacker.ThisDoor.FacingOrientation;
			if (inputPacker.UseTransform != null)
			{
				xyz = Geometry.TransformPoint(xyz, inputPacker.UseTransform);
			}
			return xyz;
		}

		public static XYZ GetListCurveMidPoint(List<Curve> inputCurve)
		{
			XYZ xyz = null;
			if (inputCurve == null || inputCurve.Count == 0)
			{
				return xyz;
			}
			xyz = XYZ.Zero;
			int num = 0;
			foreach (Curve curve in inputCurve)
			{
				xyz = xyz.Add(curve.GetEndPoint(0));
				xyz = xyz.Add(curve.GetEndPoint(1));
				num += 2;
			}
			return xyz.Divide((double)num);
		}

		public static Curve GetASameLengthOffestCurve(this Curve input, double offsetDist, XYZ normal)
		{
			Transform transform = Transform.CreateTranslation(input.GetEndPoint(1).Add(-input.GetEndPoint(0)).Normalize().CrossProduct(normal).Normalize().Multiply(offsetDist));
			return input.CreateTransformed(transform);
		}

		public static List<Curve> GetBoundaryCurves(Element inputEement)
		{
			List<Curve> list = new List<Curve>();
			if (inputEement != null)
			{
				if (inputEement is SpatialElement)
				{
					IEnumerator<IList<BoundarySegment>> enumerator = (inputEement as SpatialElement).GetBoundarySegments(new SpatialElementBoundaryOptions()).GetEnumerator();
					{
						while (enumerator.MoveNext())
						{
							IList<BoundarySegment> list2 = enumerator.Current;
							foreach (BoundarySegment boundarySegment in list2)
							{
								list.Add(boundarySegment.GetCurve());
							}
						}
						return list;
					}
				}
				List<PlanarFace> list3 = new List<PlanarFace>();
				foreach (GeometryObject geometryObject in inputEement.get_Geometry(new Options()))
				{
					Solid solid = geometryObject as Solid;
					if (null != solid)
					{
						foreach (object obj in solid.Faces)
						{
							Face face = (Face)obj;
							if (!(null == face) && Utility.IfIsZPlanarFace(face))
							{
								list3.Add(face as PlanarFace);
							}
						}
					}
				}
				list3 = (from k in list3
				orderby k.Origin.Z
				select k).ToList<PlanarFace>();
				if (list3.Count != 0)
				{
					foreach (object obj2 in list3[0].EdgeLoops)
					{
						foreach (object obj3 in ((EdgeArray)obj2))
						{
							Edge edge = (Edge)obj3;
							if (null != edge)
							{
								list.Add(edge.AsCurve());
							}
						}
					}
				}
			}
			return list;
		}

		public static bool IfIsZPlanarFace(Face inputFace)
		{
			return inputFace is PlanarFace && ((inputFace as PlanarFace).FaceNormal.IsAlmostEqualTo(XYZ.BasisZ) || (inputFace as PlanarFace).FaceNormal.IsAlmostEqualTo(-XYZ.BasisZ));
		}

		public static XYZ CalculateLstCurveMidPoint(List<Curve> lstInputCurves)
		{
			int num = 0;
			XYZ xyz = XYZ.Zero;
			foreach (Curve curve in lstInputCurves)
			{
				xyz = xyz.Add(curve.GetEndPoint(0));
				xyz = xyz.Add(curve.GetEndPoint(1));
				num += 2;
			}
			if (num == 0)
			{
				return null;
			}
			xyz = xyz.Divide((double)num);
			return xyz;
		}

		public static List<Curve> GetBoundaryCurves(FamilyInstance useFamilyInstance, out double wallWidth, Transform useTransform = null, ElementGeometryPacker inputElementGeometryPacker = null, int modeIndex = 0)
		{
			if (modeIndex == 0)
			{
				return Utility.GetBoundaryCurves_WallOpening_Param(useFamilyInstance, out wallWidth, useTransform, inputElementGeometryPacker);
			}
			return Utility.GetBoundaryCurves_WallOpening(useFamilyInstance, out wallWidth, useTransform, inputElementGeometryPacker);
		}

		public static bool IfTwoCurveIntersection_NoZ(Curve curveOne, Curve curveTwo)
		{
			double moveZValue = 0.0 - curveOne.GetEndPoint(0).Z;
			double moveZValue2 = 0.0 - curveTwo.GetEndPoint(0).Z;
			Curve curve = Utility.TransformCurveAtZAixs(curveOne, moveZValue, true);
			Curve curve2 = Utility.TransformCurveAtZAixs(curveTwo, moveZValue2, true);
			SetComparisonResult setComparisonResult = curve.Intersect(curve2);
			return setComparisonResult == SetComparisonResult.Overlap && setComparisonResult == SetComparisonResult.Subset && setComparisonResult == SetComparisonResult.Superset && setComparisonResult == SetComparisonResult.Equal;
		}

		public static Curve TransformCurveAtZAixs(Curve inputCurve, double moveZValue, bool ifAbsolute = true)
		{
			return CurveUtility.TransformCurveAtZAixs(inputCurve, moveZValue, ifAbsolute);
		}

		public static Curve ReCreatCurveAtZValue(Curve inputCurve, double wantZ)
		{
			if (!(inputCurve is Line) && !(inputCurve is Arc))
			{
				throw new ModelCheckUtilityException(Resources.Exception_ErrorCurve);
			}
			XYZ xyz = new XYZ(inputCurve.GetEndPoint(0).X, inputCurve.GetEndPoint(0).Y, wantZ);
			XYZ xyz2 = new XYZ(inputCurve.GetEndPoint(1).X, inputCurve.GetEndPoint(1).Y, wantZ);
			if (inputCurve is Line)
			{
				return Line.CreateBound(xyz, xyz2);
			}
			Arc arc = inputCurve as Arc;
			int count = arc.Tessellate().Count;
			XYZ xyz3 = arc.Tessellate()[count / 2];
			xyz3 = new XYZ(xyz3.X, xyz3.Y, wantZ);
			return Arc.Create(xyz, xyz2, xyz3);
		}

		public static bool IfHostElementPackerCanHostInRoomPacker(BaseRoomPacker inputRoomPacker, BaseHostInRoomPacker inputHostedElementPacker, out XYZ intersectionPoint)
		{
			bool result = false;
			intersectionPoint = null;
			List<KeyValuePair<Solid, ElementGeometryPacker>> list = (from kvp in inputHostedElementPacker.LstSolids
			orderby kvp.Value.CenterPoint.Z - inputRoomPacker.NowDownZ
			select kvp).ToList<KeyValuePair<Solid, ElementGeometryPacker>>();
			bool ifOnlyUseCenterPoint = inputHostedElementPacker.ThisElement.Category.Id.IntegerValue == -2000120;
			foreach (KeyValuePair<Solid, ElementGeometryPacker> keyValuePair in list)
			{
				double num = Math.Abs(keyValuePair.Value.MaxZ - keyValuePair.Value.MinZ);
				if (!Geometry.LessThan(inputRoomPacker.NowTopZ, keyValuePair.Value.MinZ) && Geometry.GreaterThan(Math.Abs(inputRoomPacker.NowTopZ - keyValuePair.Value.MinZ), 0.2 * num) && !Geometry.LessThan(keyValuePair.Value.MaxZ, inputRoomPacker.NowDownZ) && Geometry.GreaterThan(Math.Abs(keyValuePair.Value.MaxZ - inputRoomPacker.NowDownZ), 0.2 * num) && Utility.IfElementGeometryProjectZPlanarFace(keyValuePair.Value, inputRoomPacker.NowDownFace, ifOnlyUseCenterPoint))
				{
					if (null != keyValuePair.Key)
					{
						List<PlanarFace> orderedPlanarFaceForZNormal = Utility.GetOrderedPlanarFaceForZNormal(keyValuePair.Key);
						if (orderedPlanarFaceForZNormal.Count > 0)
						{
							intersectionPoint = Utility.GetMidPointForPlanarFace(orderedPlanarFaceForZNormal[0]);
							result = true;
							break;
						}
					}
					IntersectionResult intersectionResult = inputRoomPacker.NowDownFace.Project(keyValuePair.Value.CenterPoint);
					if (intersectionResult != null)
					{
						intersectionPoint = intersectionResult.XYZPoint;
					}
					result = true;
					break;
				}
				if (Utility.IfElementGeometryIntersectionWithZPlanarFace(keyValuePair.Value, inputRoomPacker.NowDownFace, ifOnlyUseCenterPoint) && Utility.IfElementGeometryProjectZPlanarFace(keyValuePair.Value, inputRoomPacker.NowDownFace, ifOnlyUseCenterPoint))
				{
					result = true;
					if (!(null != keyValuePair.Key))
					{
						intersectionPoint = inputRoomPacker.NowDownFace.Project(keyValuePair.Value.CenterPoint).XYZPoint;
						break;
					}
					List<PlanarFace> orderedPlanarFaceForZNormal2 = Utility.GetOrderedPlanarFaceForZNormal(keyValuePair.Key);
					if (orderedPlanarFaceForZNormal2.Count > 0)
					{
						intersectionPoint = Utility.GetMidPointForPlanarFace(orderedPlanarFaceForZNormal2[0]);
						result = true;
						break;
					}
					break;
				}
			}
			return result;
		}

		public static List<PlanarFace> GetOrderedPlanarFaceForZNormal(Solid input)
		{
			List<PlanarFace> list = new List<PlanarFace>();
			foreach (object obj in input.Faces)
			{
				Face face = (Face)obj;
				if (face is PlanarFace)
				{
					PlanarFace planarFace = face as PlanarFace;
					if (!(null == planarFace) && (planarFace.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ) || planarFace.FaceNormal.IsAlmostEqualTo(-XYZ.BasisZ)))
					{
						list.Add(planarFace);
					}
				}
			}
			list = (from k in list
			orderby k.Origin.Z
			select k).ToList<PlanarFace>();
			return list;
		}

		public static XYZ GetMidPointForPlanarFace(PlanarFace input)
		{
			List<Curve> list = new List<Curve>();
			foreach (CurveLoop curveLoop in input.GetEdgesAsCurveLoops())
			{
				foreach (Curve item in curveLoop)
				{
					list.Add(item);
				}
			}
			return Utility.CalculateLstCurveMidPoint(list);
		}

		public static List<Solid> GetAllSolid(GeometryElement inputValue, Transform useTransform = null, bool onlyGetStairsRun = false)
		{
			List<Solid> list = new List<Solid>();
			if (!(null == inputValue))
			{
				GeometryElement geometryElement = inputValue;
				if (useTransform != null)
				{
					geometryElement = geometryElement.GetTransformed(useTransform);
				}
				foreach (GeometryObject geometryObject in geometryElement)
				{
					if (!(null == geometryObject))
					{
						if (null != geometryObject as Solid && (geometryObject as Solid).Volume > 1E-06)
						{
							list.Add(geometryObject as Solid);
						}
						if (geometryObject is GeometryInstance && (!onlyGetStairsRun || (geometryObject as GeometryInstance).Symbol is StairsRun))
						{
							list.AddRange(Utility.GetAllSolid((geometryObject as GeometryInstance).GetSymbolGeometry((geometryObject as GeometryInstance).Transform), null, false));
						}
					}
				}
			}
			return list;
		}

		public static bool IfElementGeometryIntersectionWithZPlanarFace(ElementGeometryPacker inputValue, PlanarFace useFace, bool ifOnlyUseCenterPoint = false)
		{
			return inputValue.MaxZ > useFace.Origin.Z && inputValue.MinZ < useFace.Origin.Z && Utility.IfElementGeometryProjectZPlanarFace(inputValue, useFace, ifOnlyUseCenterPoint);
		}

		public static bool IfElementGeometryProjectZPlanarFace(ElementGeometryPacker inputValue, PlanarFace useFace, bool ifOnlyUseCenterPoint = false)
		{
			List<XYZ> list = new List<XYZ>
			{
				inputValue.MaxXPoint,
				inputValue.MinXPoint,
				inputValue.MaxYPoint,
				inputValue.MinYPoint,
				inputValue.CenterPoint
			};
			bool flag = true;
			bool flag2;
			if (!ifOnlyUseCenterPoint)
			{
				using (List<XYZ>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						XYZ inputPoint = enumerator.Current;
						flag = (flag && Utility.IfAPointProjectInFace(inputPoint, useFace, out flag2));
					}
					return flag;
				}
			}
			flag = (flag && Utility.IfAPointProjectInFace(inputValue.CenterPoint, useFace, out flag2));
			return flag;
		}

		public static bool IfAPointProjectInFace(XYZ inputPoint, Face inputFace, out bool ifPointOnFace)
		{
			IntersectionResult intersectionResult = inputFace.Project(inputPoint);
			ifPointOnFace = false;
			if (intersectionResult == null)
			{
				return false;
			}
			if (inputPoint.IsAlmostEqualTo(intersectionResult.XYZPoint))
			{
				ifPointOnFace = true;
				return true;
			}
			XYZ xyz = inputPoint.Add(-intersectionResult.XYZPoint).Normalize();
			XYZ xyz2 = inputFace.ComputeNormal(intersectionResult.UVPoint).Normalize();
			return xyz.IsAlmostEqualTo(xyz2) || xyz.IsAlmostEqualTo(-xyz2);
		}

		public static List<PlanarFace> FindZPlanarFace(GeometryElement inputGeometryElement, Transform useTransform = null)
		{
			List<PlanarFace> list = new List<PlanarFace>();
			GeometryElement geometryElement = inputGeometryElement;
			if (useTransform != null)
			{
				geometryElement = geometryElement.GetTransformed(useTransform);
			}
			foreach (GeometryObject geometryObject in geometryElement)
			{
				if (geometryObject is GeometryInstance)
				{
					list.AddRange(Utility.FindZPlanarFace((geometryObject as GeometryInstance).GetInstanceGeometry((geometryObject as GeometryInstance).Transform), null));
				}
				if (geometryObject is Solid)
				{
					foreach (object obj in (geometryObject as Solid).Faces)
					{
						Face face = (Face)obj;
						if (face is PlanarFace && !(null == face))
						{
							UV max = face.GetBoundingBox().Max;
							if (null != face && ((face as PlanarFace).ComputeNormal(max).IsAlmostEqualTo(XYZ.BasisZ) || (face as PlanarFace).ComputeNormal(max).IsAlmostEqualTo(-XYZ.BasisZ)))
							{
								list.Add(face as PlanarFace);
							}
						}
					}
				}
			}
			list = (from k in list
			orderby k.Origin.Z
			select k).ToList<PlanarFace>();
			return list;
		}

		public static List<double> GetAllLevelZVaue(Autodesk.Revit.DB.Document useDoc)
		{
			List<double> list = new List<double>();
			foreach (Element element in new FilteredElementCollector(useDoc).OfClass(typeof(Level)).ToElements())
			{
				Level level = (Level)element;
				if (level != null)
				{
					list.Add(level.Elevation);
				}
			}
			list = (from k in list
			orderby k
			select k).ToList<double>();
			return list;
		}

		public static List<KeyValuePair<X, RevitLinkInstance>> GetAllElement<X>(Autodesk.Revit.DB.Document inputDocument, BuiltInCategory inputCategory, RevitLinkInstance useLinkInstance = null) where X : Element
		{
			return LinkDocumentUtility.GetAllElement<X>(inputDocument, inputCategory, useLinkInstance);
		}

		public static bool IfGeometryPackerCanProjectToCurve(Curve inputCurve, ElementGeometryPacker tempGeometryPacker)
		{
			Curve curve = inputCurve.Clone();
			curve.MakeUnbound();
			IntersectionResult intersectionResult = inputCurve.Project(tempGeometryPacker.CenterPoint);
			IntersectionResult intersectionResult2 = curve.Project(tempGeometryPacker.CenterPoint);
			return intersectionResult.XYZPoint.IsAlmostEqualTo(intersectionResult2.XYZPoint);
		}

		public static List<XYZ> GetFamilyInstanceWidthPointAtlWallLocation(FamilyInstance useFamilyInstance, Transform useTransform = null, ElementGeometryPacker inputElementGeometryPacker = null)
		{
			List<XYZ> list = new List<XYZ>();
			Wall wall = useFamilyInstance.Host as Wall;
			if (wall != null)
			{
				bool flag;
				ElementGeometryPacker useFamilyInstanceGeometryPacker;
				Utility.TryUseElmentGeoPacker(useFamilyInstance, useTransform, inputElementGeometryPacker, out flag, out useFamilyInstanceGeometryPacker);
				if (flag)
				{
					Curve curve = (wall.Location as LocationCurve).Curve;
					if (useTransform != null)
					{
						curve = curve.CreateTransformed(useTransform);
					}
					Parameter parameter = useFamilyInstance.Symbol.get_Parameter((BuiltInParameter)Enum.Parse(typeof(BuiltInParameter), Resources.Str_ParameterName_Width));
					if (parameter != null)
					{
						foreach (IntersectionResult intersectionResult in Utility.GetFamilyInstanceWidth_ParamPoint(useFamilyInstanceGeometryPacker, curve, parameter))
						{
							list.Add(intersectionResult.XYZPoint);
						}
					}
				}
			}
			return list;
		}

		public static bool CurveCheck(Curve inputCurve)
		{
			if (inputCurve.IsBound)
			{
				return true;
			}
			Geometry.IsEqual(inputCurve.GetEndPoint(0).Z, inputCurve.GetEndPoint(1).Z);
			throw new ModelCheckUtilityException(Resources.Exception_ErrorCurve);
		}

		public static bool IfGeometryCanProjectToCurve(GeometryElement inputGeometryElement, Curve inputCurve, Transform useTransform = null)
		{
			GeometryElement geometryElement = inputGeometryElement;
			if (useTransform != null)
			{
				geometryElement = geometryElement.GetTransformed(useTransform);
			}
			ElementGeometryPacker geometryLimitValue = LinkDocumentUtility.GetGeometryLimitValue(geometryElement, null);
			return Utility.IfGeometryPackerCanProjectToCurve(inputCurve, geometryLimitValue);
		}

		private static List<Curve> GetBoundaryCurves_WallOpening_Param(FamilyInstance useFamilyInstance, out double wallWidth, Transform useTransform = null, ElementGeometryPacker inputElementGeometryPacker = null)
		{
			List<Curve> result = null;
			Wall wall = useFamilyInstance.Host as Wall;
			wallWidth = -1.0;
			if (wall != null)
			{
				wallWidth = wall.Width;
				bool flag;
				ElementGeometryPacker useFamilyInstanceGeometryPacker;
				Utility.TryUseElmentGeoPacker(useFamilyInstance, useTransform, inputElementGeometryPacker, out flag, out useFamilyInstanceGeometryPacker);
				if (flag)
				{
					Curve curve = (wall.Location as LocationCurve).Curve;
					if (useTransform != null)
					{
						curve = curve.CreateTransformed(useTransform);
					}
					Parameter parameter = useFamilyInstance.Symbol.get_Parameter((BuiltInParameter)Enum.Parse(typeof(BuiltInParameter), Resources.Str_ParameterName_Width));
					if (parameter == null)
					{
						IList<Parameter> parameters = useFamilyInstance.GetParameters(Resources.Str_ParameterName_DoorWidth);
						if (parameters.Count != 0)
						{
							parameter = parameters[0];
						}
					}
					if (parameter != null && parameter.HasValue)
					{
						List<IntersectionResult> familyInstanceWidth_ParamPoint = Utility.GetFamilyInstanceWidth_ParamPoint(useFamilyInstanceGeometryPacker, curve, parameter);
						if (familyInstanceWidth_ParamPoint != null && familyInstanceWidth_ParamPoint.Count > 0)
						{
							result = Utility.GetEndLines(wallWidth, curve, familyInstanceWidth_ParamPoint);
						}
					}
				}
			}
			return result;
		}

		private static List<IntersectionResult> GetFamilyInstanceWidth_ParamPoint(ElementGeometryPacker useFamilyInstanceGeometryPacker, Curve useCurve, Parameter useWidthParam)
		{
			List<IntersectionResult> list = new List<IntersectionResult>();
			try
			{
				double num = useWidthParam.AsDouble();
				double length = useCurve.Length;
				double endParameter = useCurve.GetEndParameter(0);
				double endParameter2 = useCurve.GetEndParameter(1);
				Curve curve = useCurve.Clone();
				Curve curve2 = useCurve.Clone();
				curve2.MakeUnbound();
				double parameter = curve2.Project(useFamilyInstanceGeometryPacker.CenterPoint).Parameter;
				curve.MakeBound(endParameter, parameter);
				double length2 = curve.Length;
				double num2 = parameter + -0.5 * num / length * (endParameter2 - endParameter);
				double num3 = parameter + 0.5 * num / length * (endParameter2 - endParameter);
				list = new List<IntersectionResult>();
				XYZ xyz = curve2.Evaluate(num2, false);
				XYZ xyz2 = curve2.Evaluate(num3, false);
				list.Add(curve2.Project(xyz));
				list.Add(curve2.Project(xyz2));
				if (list[0].XYZPoint.IsAlmostEqualTo(list[1].XYZPoint))
				{
					list = new List<IntersectionResult>();
				}
			}
			catch (Exception)
			{
				list = new List<IntersectionResult>();
			}
			return list;
		}

		private static List<Curve> GetBoundaryCurves_WallOpening(FamilyInstance useFamilyInstance, out double wallWidth, Transform useTransform = null, ElementGeometryPacker inputElementGeometryPacker = null)
		{
			List<Curve> result = null;
			Wall wall = useFamilyInstance.Host as Wall;
			wallWidth = -1.0;
			if (wall != null)
			{
				wallWidth = wall.Width;
				bool flag;
				ElementGeometryPacker useFamilyInstanceGeometryPacker;
				Utility.TryUseElmentGeoPacker(useFamilyInstance, useTransform, inputElementGeometryPacker, out flag, out useFamilyInstanceGeometryPacker);
				if (flag)
				{
					result = Utility.GetDoorCurvAtWall(useFamilyInstance, wallWidth, useTransform, wall, useFamilyInstanceGeometryPacker);
				}
			}
			return result;
		}

		private static List<Curve> GetDoorCurvAtWall(FamilyInstance useFamilyInstance, double wallWidth, Transform useTransform, Wall hostedWall, ElementGeometryPacker useFamilyInstanceGeometryPacker)
		{
			Curve curve = (hostedWall.Location as LocationCurve).Curve;
			if (useTransform != null)
			{
				curve = curve.CreateTransformed(useTransform);
			}
			curve = Utility.TransformCurveAtZAixs(curve, useFamilyInstanceGeometryPacker.CenterPoint.Z - curve.GetEndPoint(1).Z, true);
			List<Face> list = new List<Face>();
			Options options = new Options();
			foreach (GeometryObject geometryObject in hostedWall.get_Geometry(options))
			{
				if (geometryObject is Solid && null != geometryObject as Solid)
				{
					foreach (object obj in (geometryObject as Solid).Faces)
					{
						Face item = (Face)obj;
						list.Add(item);
					}
				}
			}
			List<Face> list2 = new List<Face>();
			foreach (Face face in list)
			{
				if (hostedWall.GetGeneratingElementIds(face).ToList<ElementId>().Contains(useFamilyInstance.Id))
				{
					list2.Add(face);
				}
			}
			new List<Curve>();
			List<IntersectionResult> list3 = new List<IntersectionResult>();
			foreach (Face face2 in list2)
			{
				IntersectionResultArray intersectionResultArray;
				SetComparisonResult setComparisonResult = face2.Intersect(curve, out intersectionResultArray);
				if (8 == (int)setComparisonResult)
				{
					foreach (object obj2 in intersectionResultArray)
					{
						IntersectionResult item2 = (IntersectionResult)obj2;
						list3.Add(item2);
					}
				}
			}
			if (1 == list3.Count)
			{
				Utility.AddNearPoint(curve, list3);
			}
			if (2 != list3.Count)
			{
				throw new ModelCheckUtilityException(Resources.Exception_ErrorCalculate);
			}
			return Utility.GetEndLines(wallWidth, curve, list3);
		}

		private static void AddNearPoint(Curve useCurve, List<IntersectionResult> useEndPoints)
		{
			if (useCurve.GetEndPoint(0).DistanceTo(useEndPoints[0].XYZPoint) > useCurve.GetEndPoint(1).DistanceTo(useEndPoints[0].XYZPoint))
			{
				if (!useCurve.GetEndPoint(1).IsAlmostEqualTo(useEndPoints[0].XYZPoint))
				{
					useEndPoints.Add(useCurve.Project(useCurve.GetEndPoint(1)));
					return;
				}
				useEndPoints.Add(useCurve.Project(useCurve.GetEndPoint(0)));
				return;
			}
			else
			{
				if (!useCurve.GetEndPoint(0).IsAlmostEqualTo(useEndPoints[0].XYZPoint))
				{
					useEndPoints.Add(useCurve.Project(useCurve.GetEndPoint(0)));
					return;
				}
				useEndPoints.Add(useCurve.Project(useCurve.GetEndPoint(1)));
				return;
			}
		}

		private static List<Curve> GetEndLines(double wallWidth, Curve useCurve, List<IntersectionResult> useEndPoints)
		{
			Curve curve = useCurve.Clone();
			curve.MakeUnbound();
			double parameter = curve.Project(useEndPoints[0].XYZPoint).Parameter;
			double parameter2 = curve.Project(useEndPoints[1].XYZPoint).Parameter;
			try
			{
				curve.MakeBound(parameter, parameter2);
			}
			catch (Exception)
			{
				throw;
			}
			Curve curve2 = CurveUtility.CreateOffsetCurve(curve, wallWidth / 2.0);
			Curve curve3 = CurveUtility.CreateOffsetCurve(curve, -wallWidth / 2.0);
			Line item = Line.CreateBound(curve2.GetEndPoint(0), curve3.GetEndPoint(0));
			Line item2 = Line.CreateBound(curve2.GetEndPoint(1), curve3.GetEndPoint(1));
			return new List<Curve>
			{
				item,
				item2
			};
		}

		private static void TryUseElmentGeoPacker(FamilyInstance useFamilyInstance, Transform useTransform, ElementGeometryPacker inputElementGeometryPacker, out bool sucessTag, out ElementGeometryPacker useFamilyInstanceGeometryPacker)
		{
			sucessTag = false;
			if (inputElementGeometryPacker != null)
			{
				sucessTag = true;
				useFamilyInstanceGeometryPacker = inputElementGeometryPacker;
				return;
			}
			useFamilyInstanceGeometryPacker = LinkDocumentUtility.TryGetGeometryPacker(out sucessTag, useFamilyInstance, useTransform);
		}
	}
}
